' CW Blinker ' ' FDIM 2014 QRPP HAMfest STICK for PICAXE 14M2 ' ' Written by Dave Rajnauth, VE3OOI (c) 2014 ' Version 1.1 June 2014 ' Usage: ' To program push and hold the push button until LED stops flashing ' The program check the button state before it start sending the start of the message ' Enter characters A-Z, 0-9 on the keyboard (case does not matter). ' Use BAACKSPACE to reset and start re-entering keystokes (deletes everthing captures and restart) ' Use ESC to exit from keyboard entry mode and send last message save ' Use ENTER to save current message and send the newly created message ' If you have a program cable attached, you can uncomment the #define ShowTerminal line ' to show keystrokes captures and the current message saved. ' Physical Connections ' Pin Function ' 5 c.2 KBCLK ' 6 c.1 KBDATA ' 7 c.0 Osc On (3.6864 Mhz) ' 11 b.2 LED ' 8 B.1 MeSquare Pad for personal use ' 9 B.2 MeSquare Pad for personal use ' 10 B.3 MeSquare Pad for personal use ' declarations #picaxe 14m2 ' this is a PICAXE 14M2 '#define ShowTerminal ' define this lable to display a terminal with debugging information #ifdef ShowTerminal #com 1 ' open terminal after download for debugging #terminal 9600 #endif ' CW encoded character lookup table TABLE 0,(%01000010, %10000100, %10100100, %10000011, %00000001, %00100100, %11000011, %00000100, _ %00000010, %01110100, %10100011, %01000100, %11000010, %10000010, %11100011, %01100100, %11010100, _ %01000011, %00000011, %10000001, %00100011, %00010100, %01100011, %10010100, %10110100, %11000100, _ %11111101, %01111101, %00111101, %00011101, %00001101, %00000101, %10000101, %11000101, %11100101, _ %11110101) ' Keyboard Scan Code lookup table TABLE 37,(28,50,33,35,36,43,52,51,67,59,66,75,58,49,68,77,21,45,27,44,60,42,29,34,53,26,69,22,30,38,37,46,54,61,62,70) 'TABLE 37,($1c,$32,$21,$23,$24,$2b,$34,$33,$43,$3b,$42,$4b,$3a,$31,$44,$4d,$15,$2d,$1b,$2c,$3c,$2a, _ '$1d,$22,$35,$1a,$45,$16,$1e,$26,$25,$2e,$36,$3d,$3e,$46) ' Message to send EEPROM 0,(17,"HELLO FROM VE300I") Symbol LookupTableLength = 36 'set length of the CW/KBD lookup table Symbol KBLookupTableStart = 37 'Starting address of the KBD scan code lookup table Symbol Dit_length = 120 'set length of a dot Symbol Dah_length = 360 'set length of a dash 3x dit Symbol ASCIICharacter = b0 'set register for Ascii character message to be send via Morse. Symbol CWCharacter = b1 'set register for Translated CW Character. Symbol ASCIILength = b2 'set register for length of Ascii character message Symbol CWLength = b3 'set register for length of CW character. Symbol i = b4 'counter Symbol j = b5 'counter Symbol k = b6 'counter Symbol KeyPress = b7 'Keyboard Character received Symbol TempMemoryStart = b8 'starting location to save temporary string before writing to message (eeprom location 0) Symbol TempMemorySize = b9 'size of temporary string captured (running total of number of characters entered) ' Program setup here Setup: setfreq m8 ' set Fosc for 8 Mhz ' Start program entry here Start: high c.4 high c.0 for i=0 to 2 low c.4 pause 500 high c.4 pause 500 next i ' Main program loop Main: if pinB.2 != 1 then keyled %00000111 RestartKBD: #ifdef ShowTerminal sertxd("\r\n") READ 0,ASCIILength for i=1 to ASCIILength read i, ASCIICharacter ' read eeprom to get current message sertxd(ASCIICharacter) next i sertxd("\r\n") #endif let TempMemoryStart = LookupTableLength + KBLookupTableStart + 2 'Actual location for keyboard buffer 'TempMemoryStart-1 is the size of the text entered let TempMemorySize = 0 ' reset actual size of captured array of characters do KBDTimeOut: let KeyPress = 0 ' Note: Each keypress generates two characters KBIN [1000,KBDTimeOut], KeyPress ' Check for keypress and read first value sent, 1s timeout and loop KBIN KeyPress ' Two values are sent, second value is what we want if KeyPress > 0 then ' if a valid keypress then change to ASCII Character gosub LookupKBDScanCode endif if ASCIICharacter != 0 then ' valid ascii character so save into temp buffer #ifdef ShowTerminal sertxd(ASCIICharacter) #endif WRITE TempMemoryStart, ASCIICharacter inc TempMemoryStart inc TempMemorySize end if if KeyPress = 102 then ' Backspace key pressed so reset everything goto RestartKBD else if KeyPress = 118 then ' ESC key pressed so exit out and send message goto SendMessage end if loop while KeyPress != $5a ' if return pressed then exit loop and continue let TempMemoryStart = LookupTableLength + KBLookupTableStart + 1 'location to store length of buffer write TempMemoryStart,TempMemorySize inc TempMemoryStart let j = TempMemoryStart + TempMemorySize let k = 1 #ifdef ShowTerminal sertxd("\r\n") for i=TempMemoryStart to j read i, ASCIICharacter ' read temp buffer to get current message write k, ASCIICharacter inc k sertxd(ASCIICharacter) next i write 0,TempMemorySize sertxd("\r\n") #else for i=TempMemoryStart to j read i, ASCIICharacter ' read temp buffer to get current message write k, ASCIICharacter inc k next i write 0,TempMemorySize #endif endif pause 2000 ' wait 2 seconds before continuing (gap between messages) ' Entry point to start sending message in EEPROM SendMessage: READ 0,ASCIILength for i=1 to ASCIILength read i, ASCIICharacter ' read eeprom to get current message gosub SendCW ' send character using Morse next i high c.4 ' ensure osc and led are off high c.0 gosub Word_sp goto Main ' Routine to convert keyscan value to ASCII ' Keyboard scan codes '$1c, 28 - a Add 64 to array offset (ie 0 for this location in array) for ascii value for alphabet characters '$32, 50 - b '$21, 33 - c '$23, 35 - d '$24, 36 - e '$2b, 43 - f '$34, 52 - g '$33, 51 - h '$43, 67 - I '$3b, 59 - j '$42, 66 - k '$4b, 75 - l '$3a, 58 - m '$31, 49 - n '$44, 68 - o '$4d, 77 - p '$15, 21 - q '$2d, 45 - r '$1b, 27 - s '$2c, 44 - t '$3c, 60 - u '$2a, 42 - v '$1d, 29 - w '$22, 34 - x '$35, 53 - y '$1a, 26 - z '$45, 69 - 0 Add 21 to array offset (ie 26 for this location in array) for ascii value for numeric characters '$16, 22 - 1 '$1e, 30 - 2 '$26, 38 - 3 '$25, 37 - 4 '$2e, 46 - 5 '$36, 54 - 6 '$3d, 61 - 7 '$3e, 62 - 8 '$46, 70 - 9 LookupKBDScanCode: if KeyPress = 41 then ' Space bar pressed so ascii is 32 ASCIICharacter = 32 return end if let j = KBLookupTableStart ' set the start and stop location for lookup table in eeprom let k = KBLookupTableStart+LookupTableLength let ASCIICharacter = 0 do ' read sequentually each keyscan value in eeprom readtable j, ASCIICharacter inc j loop while ASCIICharacter != KeyPress and j < k ' compare eeprom to keyscan exit when matches or not found if ASCIICharacter = KeyPress then let ASCIICharacter = j - KBLookupTableStart ' if keyscan value is found in table, convert to the offset into the table if ASCIICharacter > 26 then let ASCIICharacter = ASCIICharacter + 21 ' if its in the numeric part of lookup, add 21 to convert offset to ascii else let ASCIICharacter = ASCIICharacter + 64 ' if its in the alpha part of lookup, add 21 to convert offset to ascii end if else let ASCIICharacter = 0 ' not found and return NULL endif return ' Routine to send one Ascii character using Morse Code SendCW: gosub LookupCW let CWLength = CWCharacter & %00000111 'Lower 3 bits is the length of the CW charater if CWLength = 0 then gosub Word_sp return endif ' for j=1 to CWLength 'loop through correct no. of times for number of elements if CWCharacter >= 128 then gosub Dash 'test MS digit of ch. If it is 1 goto the Dah sub routine else gosub Dot 'if it is 0 goto the Dit sub routine endif let CWCharacter = CWCharacter * 2 'do a left shift on all the bits in ch. next gosub Char_sp 'Character send so insert a intercharacter space return ' Routine to convert ascii to Morse encoded character ' Lookup table for Morse ' for alpha characters subtract 65 from ascii value to get offset in table ' for numeric characters subtract 26 from ascii value to get offset in table ' 'const unsigned char cwLooup[CW_LOOKUP_TABLE_SIZE] = { ' %xxxxxNNN NNN = number of bits for character & xxxxx is 0 for dot, 1 for dash ' %01000010, ' A Subtract 65 from ascii value ' %10000100, ' b ' %10100100, ' c ' %10000011, ' d ' %00000001, ' e ' %00100100, ' f ' %11000011, ' g ' %00000100, ' h ' %00000010, ' i ' %01110100, ' j ' %10100011, ' k ' %01000100, ' l ' %11000010, ' m ' %10000010, ' n ' %11100011, ' o ' %01100100, ' p ' %11010100, ' q ' %01000011, ' r ' %00000011, ' s ' %10000001, ' t ' %00100011, ' u ' %00010100, ' v ' %01100011, ' w ' %10010100, ' x ' %10110100, ' y ' %11000100, ' z ' %11111101, ' 0 [26] ie 48-26=22 Subtract 22 from ascii value ' %01111101, ' 1 ' %00111101, ' 2 ' %00011101, ' 3 ' %00001101, ' 4 ' %00000101, ' 5 ' %10000101, ' 6 ' %11000101, ' 7 ' %11100101, ' 8 ' %11110101, ' 9 ' }' ' That is: 'A - 66 B - 132 C - 164 D - 131 E - 1 F - 36 'G - 195 H - 4 I - 2 J - 116 K - 163 L - 68 'M - 194 N - 130 O - 227 P - 100 Q - 212 R - 67 'S - 3 T - 129 U - 35 V - 20 W - 99 X - 148 'Y - 180 Z - 196 1 - 125 2 - 61 3 - 29 4 - 13 '5 - 5 6 - 133 7 - 197 8 - 229 9 - 245 0 - 253 LookupCW: if ASCIICharacter > 64 then let ASCIICharacter = ASCIICharacter - 65 else if ASCIICharacter > 47 then let ASCIICharacter = ASCIICharacter - 22 else let CWCharacter = 0 return end if readtable ASCIICharacter, CWCharacter ' read CW value from table return ' Routine to send a dot Dot: low c.0 ' turn on osc for dit_length low c.4 ' turn on LED for dit_length pause Dit_Length ' pause for dit_length high c.0 ' turn on osc for dit_length high c.4 ' turn on LED for dit_length pause Dit_Length ' character spacing return ' return to look at next element of ch. ' Routine to send a dash Dash: low c.0 ' turn on osc for dit_length low c.4 ' turn on LED for dit_length pause Dah_Length ' pause for dit_length high c.0 ' turn on osc for dit_length high c.4 ' turn on LED for dit_length pause Dit_Length ' character spacing return ' return to look at next element of ch. ' Routine to generate time delay between Morse words Word_sp: pause Dah_Length ' pause for 7x dit length for space between words but alread waited 1 dit length pause Dah_Length ' each dah length = 3x dit length return 'return to get next ch. ' Routine to generate time delay between Morse characters Char_sp: pause Dit_Length ' pause for 3x dit length but already paused 1 dit length pause Dit_Length ' pause for 7x dit length return 'return to get next ch.